home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / ingres04.lzh / source / support / restore.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-18  |  25.0 KB  |  1,083 lines

  1. # include    <stdio.h>
  2. # include    <ingres.h>
  3. # include    <aux.h>
  4. # include    <catalog.h>
  5. # include    <access.h>
  6. # include    <batch.h>
  7. # include    <opsys.h>
  8. # include    <lock.h>
  9. # include    <symbol.h>
  10. # include    <resp.h>
  11. # include    <dirent.h> 
  12. # include    <stdlib.h>
  13. # include    <signal.h>
  14. # include    <setjmp.h>
  15.  
  16. /*
  17. ** INGRES crash recovery processor
  18. **    to recover a database you must be the dba or the ingres superuser
  19. **    RESTORE attempts to complete updates from batch files left in a
  20. **    database.  After finishing all the batch files it calls PURGE.
  21. */
  22.  
  23. # ifndef PURGE
  24. # define    PURGE        "purge"
  25. # endif PURGE
  26.  
  27. /* first file to close on error */
  28. # define    CLOSEFILES     3
  29.  
  30. extern int    Status;
  31. extern char    *Usercode;
  32. char        Utemp[2];
  33. char        *Fileset;
  34. char        Berror;        /* batch error */
  35. char        Error;
  36. extern char    Ask;
  37. extern char    Superuser;
  38. extern char    All;
  39. extern char    Qrymod;
  40. int        Direc        = CLOSEFILES - 1;
  41. extern int    Wait_action;
  42. short        tTvect[100];
  43. short        tTdbu[100];
  44. struct resp    Resp;
  45. DESC        Btreesec;
  46. int        Btree_fd;
  47. jmp_buf        Jmpbuffer;    /* buffer for nonlocal goto's on an error condition */
  48.  
  49.  
  50. main(argc, argv)
  51. int    argc;
  52. char    *argv[];
  53. {
  54.     register int    fd;
  55.     register int    i;
  56.     register char    *dbname;
  57.     extern char    *Proc_name;
  58.     auto int    stat;
  59.     extern    void    (*ExitFn)();
  60.     extern  void    rubproc();
  61.     char        *nargv[20];
  62.     char        **avp;
  63.     char        **fvp;
  64.     extern char    *Flagvect[];
  65.     extern char    *getnxtdb();
  66.     char        *lookucode();
  67.  
  68.     Proc_name = "RESTORE";
  69.  
  70.     /* check param list */
  71.     argv[argc] = NULL;
  72. #     ifdef xTTR1
  73.     tTrace(argv, 'T', tTvect, 100);
  74.     tTrace(argv, 'Z', tTdbu, 100);
  75. #    endif
  76.  
  77.     initialize(argc, argv);
  78.  
  79.     /* do it to it */
  80.     ExitFn = rubproc;
  81.     signal(SIGQUIT, exit);
  82.     while (dbname = getnxtdb())
  83.     {
  84.         Berror = Error = 0;
  85.  
  86.         /* first restart point for this database */
  87.         setjmp(Jmpbuffer);
  88.         if (Error)    /* if set, will cause skip to next database */
  89.             continue;
  90.         printf("\nRestoring database: %s\t", dbname);
  91.  
  92.         acc_init();
  93.         printf("owner: %s\n", lookucode(Admin.adhdr.adowner));
  94.  
  95.         /* set exclusive lock on data base */
  96.         db_lock(M_EXCL);
  97.  
  98.         restore();    /* recover batch update and modify files */
  99.         printf("\tRecovery of batch files complete.\n");
  100.  
  101.         /*
  102.         ** second restart point for this database
  103.         **    the batch files are completed and now the system
  104.         **    relations need checking
  105.         */
  106.         setjmp(Jmpbuffer);
  107.         if (Error)        /* again, may cause skipping to next database */
  108.             continue;
  109.         printf("\tChecking system relations\n");
  110.  
  111.  
  112.         /*
  113.         ** check the relation relation
  114.         **    this will mean checking for file existence,
  115.         **    and whether the relstat bits are supported by
  116.         **    the information in the other catalogs.
  117.         */
  118.         checkrel();
  119.  
  120.         /*
  121.         ** check the attribute relation
  122.         **    for each tuple in the attribute relation, there must
  123.         **    be a tuple in the relation relation.
  124.         **    the indexes relation doesn't need to be reverse checked
  125.         **    into the relation relation since the order things are
  126.         **    handled else where in the system is in the correct
  127.         **    order.  All the other catalogs need to be reverse checked.
  128.         */
  129.         checkatts();
  130.  
  131.         /* only check the qrymod catalogs if qrymod is turned on */
  132.         if (Qrymod)
  133.         {
  134.             /* check the protect relation */
  135.             checkprotect();
  136.  
  137.             /* check the integrities relation */
  138.             checkinteg();
  139.  
  140.             /*
  141.             ** check the tree relation
  142.             ** must be done last since it depends upon
  143.             ** a state of the system relations provided
  144.             ** by the other check... routines.
  145.             */
  146.             checktree();
  147.         }
  148.  
  149.         /* finished, close up the database and go on to the next */
  150.         closecatalog(TRUE);
  151.         unldb();
  152.         acc_close();
  153.  
  154.         /* call PURGE if no errors */
  155.         if (!Berror && !Error)
  156.         {
  157.             printf("\tCalling purge: ");
  158.             fflush(stdout);
  159.             if ((i = fork()) == -1)
  160.                 printf("Can't fork\n");
  161.             else if (!i)
  162.             {
  163.                 avp = nargv;
  164.                 *avp++ = "Purge";
  165.                 for (fvp = Flagvect; *fvp != NULL; )
  166.                     *avp++ = *fvp++;
  167.                 *avp++ = dbname;
  168.                 *avp++ = 0;
  169. #                ifdef    xTTR2
  170.                 if (tTf(0, 1))
  171.                     for (avp = nargv, i = 0; *avp != NULL; avp++, i++)
  172.                         printf("%d %s\n", i, *avp);
  173. #                endif
  174.                 for (i=3; i <= NOFILE; i++)
  175.                     close(i);
  176.                 execv(ztack(Pathname, "/bin/purge"), nargv);
  177.                 execvp(PURGE, nargv);
  178.                 printf("Cannot exec %s\n", PURGE);
  179.                 exit(-1);
  180.             }
  181.             else
  182.                 wait(&stat);
  183.         }
  184.     }
  185. }
  186. /*
  187. ** RESTORE -- find the batch files and process them
  188. */
  189. restore()
  190. {
  191.     DESC            descr;
  192.     register    DIR    *dirp;
  193.     register struct    dirent  *dp;
  194.     register int        i;
  195.     extern char        *Fileset;
  196.     extern         void    uperr(), (*ExitFn)();
  197.     void            (*tmpfn)();
  198.     char            *lookucode();
  199.     char            *fname;
  200.  
  201.     if ( (dirp = opendir(".")) == NULL )
  202.         syserr("Can't open data base directory");
  203.     bmove(Usercode, Utemp, UCODE_SZ);
  204.     Batch_recovery = 1;
  205.     tmpfn = ExitFn;
  206.     ExitFn = uperr;
  207.  
  208.     /* restart point */
  209.     setjmp(Jmpbuffer);
  210.     for ( dp = readdir(dirp) ; dp != NULL ; dp = readdir(dirp) )
  211.     {
  212.         fname = dp->d_name;
  213.         if ( !strcmp(".",fname) || !strcmp("..",fname) )
  214.             continue;
  215.         if (bequal("_SYSbatch", fname, 9))
  216.         {
  217.             Fileset = &fname[9];
  218.             Batch_fp = open(batchname(), O_RDONLY);
  219.             Batch_cnt = BATCHSIZE;
  220.             getbatch(&Batchhd, sizeof(Batchhd));
  221.             printf("\tFound batch file:  %s\n", fname);
  222.             printf("\tRelation: %s\tUser: %s\n", Batchhd.rel_name,
  223.                 lookucode(Batchhd.userid));
  224.             close(Batch_fp);
  225.             bmove(Batchhd.userid, Usercode, UCODE_SZ);
  226.             if(ask("\tUpdate? "))
  227.                 update();
  228.         }
  229.         if (bequal(MODBATCH, fname, sizeof(MODBATCH) - 1))
  230.         {
  231.             Fileset = &fname[sizeof(MODBATCH) - 1];
  232.             if ((Batch_fp = open(dp->d_name, O_RDONLY)) < 0)
  233.                 syserr("Can't open %s", dp->d_name);
  234.             Batch_cnt = 0;
  235.             if((i = getbatch(&descr, sizeof(descr))) != sizeof(descr))
  236.                 syserr(" cant read %d",i);
  237.             printf("\tFound incomplete modify of %.12s, user = %s\n",
  238.                 descr.reldum.relid, lookucode(descr.reldum.relowner));
  239.  
  240.             bmove(descr.reldum.relowner, Usercode, sizeof(descr.reldum.relowner));
  241.             close(Batch_fp);
  242.             if (ask("\tComplete? "))
  243.                 modupdate();
  244.         }
  245.     }
  246.     bmove(Utemp, Usercode, UCODE_SZ);
  247.     ExitFn = tmpfn;
  248.     closedir(dirp);
  249. }
  250. /*
  251. ** handles syserr's in the update processor
  252. */
  253. uperr()
  254. {
  255.  
  256.     if (Batch_fp)
  257.         close(Batch_fp);
  258.     Berror++;
  259.     longjmp(Jmpbuffer,1);
  260. }
  261.  
  262.  
  263.  
  264. /*
  265. ** Catch errors in other places
  266. */
  267. rubproc()
  268. {
  269.     register int        i;
  270.     register struct desxx    *p;
  271.     extern struct desxx    Desxx[];
  272.     extern int        Acc_init;
  273.  
  274.     Error++;
  275.     printf("Unable to restore!\n");
  276.  
  277.     /* restore user code */
  278.     bmove(Utemp, Usercode, sizeof Utemp);
  279.  
  280.     /* close all possible files */
  281.     if (Acc_init)
  282.     {
  283.         closecatalog(TRUE);
  284.         unldb();
  285.         acc_close();
  286.     }
  287.  
  288.     /* close users file */
  289.     getuser(0);
  290.  
  291.     /* get everything else */
  292.     for (i = Direc + 1; i <= NOFILE; i++)
  293.         close(i);
  294. }
  295. /*
  296. ** looks up user by usercode in users file
  297. */
  298. char *
  299. lookucode(ucode)
  300. char    ucode[2];
  301. {
  302.     static char    buf[MAXLINE + 1];
  303.     register char    *p;
  304.  
  305.     if (getuser(ucode, buf))
  306.         syserr("cannot identify user %.2s", ucode);
  307.     for (p = buf; *p != ':'; p++);
  308.     *p = 0;
  309.     return (buf);
  310. }
  311. /*
  312. ** CHECKATTS
  313. **    Checks that all attributes are in a relation
  314. */
  315. checkatts()
  316. {
  317.     extern DESC        Reldes, Attdes;
  318.     register int        i;
  319.     register int        once;
  320.     TID            tid, limtid, reltid;
  321.     char            key[MAXTUP];
  322.     struct attribute    atttup;
  323.     struct relation        reltup;
  324.     char            lastrel[MAXNAME + 2];
  325.  
  326.     once = 0;
  327.     opencatalog("relation", OR_WRITE);
  328.     opencatalog("attribute", OR_WRITE);
  329.     clearkeys(&Attdes);
  330.     lastrel[0] = '\0';
  331.     if (find(&Attdes, NOKEY, &tid, &limtid))
  332.         syserr("CHECKATT: find");
  333.  
  334.     while (!(i = get(&Attdes, &tid, &limtid, &atttup, TRUE)))
  335.     {
  336.         if (bequal(atttup.attrelid, lastrel, MAXNAME + 2))
  337.             continue;
  338.  
  339.         clearkeys(&Reldes);
  340.         setkey(&Reldes, key, atttup.attrelid, ATTRELID);
  341.         setkey(&Reldes, key, atttup.attowner, ATTOWNER);
  342.  
  343.         if (i = getequal(&Reldes, key, &reltup, &reltid))
  344.         {
  345.             if (i < 0)
  346.                 syserr("ATTCHECK: getequal");
  347.             if (!once++)
  348.                 printf("\tNo relation for attribute(s):\n");
  349.             printf("\t");
  350.             printup(&Attdes, &atttup);
  351.             if (ask("\tDelete?"))
  352.                 if (i = delete(&Attdes, &tid))
  353.                     syserr("ATTCHECK: delete=%d", i);
  354.         }
  355.         else
  356.             bmove(atttup.attrelid, lastrel, MAXNAME + 2);
  357.     }
  358.  
  359.     if (i < 0)
  360.         syserr("ATTCHECK: get=%d", i);
  361. }
  362. /*
  363. ** CHECKREL -- check relation relation against every thing else
  364. **
  365. **    Each tuple in the relation relation is read and each verifiable
  366. **    characteristic is checked for accuracy.  Including the existence
  367. **    of the physical file (if not a view), the qrymod definition if
  368. **    appropriate and the secondary indexing.
  369. */
  370.  
  371. checkrel()
  372. {
  373.     extern DESC    Reldes;
  374.     register int    i, j;
  375.     struct relation    rel;
  376.     TID        rtid, limtid;
  377.     char        fname[MAXNAME + 3];
  378.  
  379.     /* setup for search of entire relation */
  380.     opencatalog("relation", OR_WRITE);
  381.     clearkeys(&Reldes);
  382.     if (find(&Reldes, NOKEY, &rtid, &limtid))
  383.         syserr("CHECKREL: find");
  384.  
  385.     /* loop until all tuples checked */
  386.     for (;;)
  387.     {
  388.         /* for each tuple in the rel-rel */
  389.         i = get(&Reldes, &rtid, &limtid, &rel, TRUE);
  390.         if (i > 0)
  391.             break;    /* have finished */
  392.         if (i < 0)
  393.             syserr("CHECKREL: get=%d", i);
  394.  
  395.         /* if not a view, check for the file */
  396.         if ((rel.relstat & S_VIEW) != S_VIEW)
  397.         {
  398.             ingresname(rel.relid, rel.relowner, fname);
  399.             if ((j = open(fname, O_RDWR)) == -1)
  400.             {
  401.                 printf("\tNo file for:\n\t");
  402.                 printup(&Reldes, &rel);
  403.                 if (ask("\tDelete tuple? "))
  404.                 {
  405.                     if(j = delete(&Reldes, &rtid))
  406.                         syserr("CHECKREL: delete=%d", j);
  407.                     continue;
  408.                 }
  409.                 else
  410.                     /* don't call purge the file might still be there */
  411.                     Error++;
  412.             }
  413.             else
  414.                 close(j);
  415.         }
  416.  
  417.         /* does it think that it has a secondary index */
  418.         if (rel.relindxd > 0)
  419.         {
  420.             /* does it really have an index? */
  421.             if (!hasndx(rel.relid, rel.relowner))
  422.             {
  423.                 /* no, should it be fixed */
  424.                 printf("\tNo indexes entry for primary relation:\n\t");
  425.                 printup(&Reldes, &rel);
  426.                 if (ask("\tAdjust? "))
  427.                 {
  428.                     /* fix up relation relation entry */
  429.                     rel.relindxd = 0;
  430.                     if (i = replace(&Reldes, &rtid, &rel, FALSE))
  431.                         syserr("CHECKREL: replace=%d", i);
  432.                 }
  433.             }
  434.         }
  435.  
  436.         /* does it think that it is a secondary index */
  437.         if (rel.relindxd == SECINDEX)
  438.         {
  439.             /* check to make sure */
  440.             if (!isndx(rel.relid, rel.relowner))
  441.             {
  442.                 /* none, what should be done? */
  443.                 printf("\tNo indexes entry for index:\n\t");
  444.                 printup(&Reldes, &rel);
  445.                 if(ask("\tDelete? "))
  446.                 {
  447.                     /*
  448.                     ** get rid of rel-rel tuple for
  449.                     ** secondary index,
  450.                     ** purge will do rest of
  451.                     ** removal if necessary
  452.                     */
  453.                     if (i = delete(&Reldes, &rtid))
  454.                         syserr("CHECKREL: delete=%d", i);
  455.                     continue;    /* go on to next tuple */
  456.                 }
  457.             }
  458.         }
  459.  
  460.         /* if qrymod on in the database, check those catalogs too */
  461.         if (Qrymod)
  462.         {
  463.             /*
  464.             ** cannot deal with S_VBASE since there is no way to
  465.             ** find the tree catalog entries without decoding the
  466.             ** 'treetree' fields.
  467.             **
  468.             ** check to see if this is a view
  469.             */
  470.             if ((rel.relstat & S_VIEW) && !havetree(rel.relid, rel.relowner, mdVIEW))
  471.             {
  472.                 /* no entry, should it be fixed? */
  473.                 printf("\tNo tree entry for this view:\n\t");
  474.                 printup(&Reldes, &rel);
  475.                 if (ask("\tDelete tuple? "))
  476.                 {
  477.                     /* delete relation entry */
  478.                     if (i = delete(&Reldes, &rtid))
  479.                         syserr("CHECKREL: delete=%d", i);
  480.                     continue;    /* skip to next entry in rel-rel */
  481.                 }
  482.             }
  483.  
  484.             /* check to see if has 'protect' entry */
  485.             if ((rel.relstat & S_PROTUPS) && !isprot(rel.relid, rel.relowner, -1))
  486.             {
  487.                 /* no entry, should the bit be reset */
  488.                 printf("\tNo protect entry for:\n\t");
  489.                 printup(&Reldes, &rel);
  490.                 if (ask("\tAdjust? "))
  491.                 {
  492.                     /* fix the bit */
  493.                     rel.relstat &= ~S_PROTUPS;
  494.                     if (i = replace(&Reldes, &rtid, &rel, FALSE))
  495.                         syserr("CHECKREL: replace=%d", i);
  496.                 }
  497.             }
  498.  
  499.             /* check to see if has 'integrities entry */
  500.             if ((rel.relstat & S_INTEG) && !isinteg(rel.relid, rel.relowner, -1))
  501.             {
  502.                 /* no entry, should bit be reset */
  503.                 printf("\tNo integrities entry for:\n\t");
  504.                 printup(&Reldes, &rel);
  505.                 if (ask("\tAdjust? "))
  506.                 {
  507.                     /* fix up the bit */
  508.                     rel.relstat &= ~S_INTEG;
  509.                     if (i = replace(&Reldes, &rtid, &rel, FALSE))
  510.                         syserr("CHECKREL: replace=%d", i);
  511.                 }
  512.             }
  513.         }
  514.     }
  515. }
  516. /*
  517. ** HASNDX -- the relation indicated an index, check it out
  518. **
  519. **    will search the index relation for all secondary indexes
  520. **    and check to see that each secondary index named has an
  521. **    entry in the relation relation.
  522. */
  523. hasndx(id, own)
  524. char    id[MAXNAME];
  525. char    own[2];
  526. {
  527.     register int    hasindexes;
  528.     register int    i, j;
  529.     extern DESC    Reldes, Inddes;
  530.     TID        rtid;
  531.     struct relation    rkey, rel;
  532.     TID        itid, ihitid;
  533.     struct index    ikey, ind;
  534.  
  535.     /* presume that answer is negative */
  536.     hasindexes = FALSE;
  537.  
  538.     /* set search for all tuples with 'id' and 'own' in indexes */
  539.     opencatalog("indexes", OR_WRITE);
  540.     clearkeys(&Inddes);
  541.     setkey(&Inddes, &ikey, id, IRELIDP);
  542.     setkey(&Inddes, &ikey, own, IOWNERP);
  543.     if (find(&Inddes, EXACTKEY, &itid, &ihitid, &ikey))
  544.         syserr("HASNDX: find");
  545.  
  546.     /* for each possible tuple in the indexes relation */
  547.     for (;;)
  548.     {
  549.         i = get(&Inddes, &itid, &ihitid, &ind, TRUE);
  550.  
  551.         /* check return values */
  552.         if (i < 0)
  553.             syserr("HASNDX: get=%d\n", i);
  554.         if (i > 0)
  555.             break;    /* finished */
  556.  
  557.         /* if key doesn't match, skip to next tuple */
  558.         if(kcompare(&Inddes, &ikey, &ind))
  559.             continue;
  560.         hasindexes = TRUE;
  561.  
  562.         /* verify that primary entry for sec index exists */
  563.         opencatalog("relation", OR_WRITE);
  564.         clearkeys(&Reldes);
  565.         setkey(&Reldes, &rkey, ind.irelidi, RELID);
  566.         setkey(&Reldes, &rkey, ind.iownerp, RELOWNER);
  567.         if (j = getequal(&Reldes, &rkey, &rel, &rtid, FALSE))
  568.         {
  569.             /* one doesn't exist, should we ignore it */
  570.             if (j < 0)
  571.                 syserr("HASNDX: getequal=%d", j);
  572.             printf("\tNo secondary index for indexes entry:\n\t");
  573.             printup(&Inddes, &ind);
  574.             if (ask("\tDelete? "))
  575.             {
  576.                 /* get rid of bad entry in indexes relation */
  577.                 if (j = delete(&Inddes, &itid))
  578.                     syserr("HASNDX: delete=%d", j);
  579.                 hasindexes = FALSE;
  580.             }
  581.         }
  582.     }
  583.     return (hasindexes);
  584. }
  585. /*
  586. ** ISNDX -- so you think that you're a secondary index, I'll check it out.
  587. **
  588. **    searches the indexes relation for the name of the primary relation
  589. **    and check to see if the primary is real.  Will also update the
  590. **    'relindxd' field of the primary if it isn't correct.
  591. */
  592. isndx(id, own)
  593. char    id[MAXNAME];
  594. char    own[2];
  595. {
  596.     register int    isindex;
  597.     register int    i;
  598.     extern DESC    Inddes;
  599.     TID        itid;
  600.     struct index    ind, ikey;
  601.     extern DESC    Reldes;
  602.     TID        rtid;
  603.     struct relation    rel, rkey;
  604.  
  605.     /* search for tuple in index relation, should only be one */
  606.     opencatalog("indexes", OR_WRITE);
  607.     clearkeys(&Inddes);
  608.     setkey(&Inddes, &ikey, id, IRELIDI);
  609.     setkey(&Inddes, &ikey, own, IOWNERP);
  610.     if (i = getequal(&Inddes, &ikey, &ind, &itid))
  611.     {
  612.         /* there isn't a tuple in the indexes relation */
  613.         if (i < 0)
  614.             syserr("ISNDX: getequal=%d", i);
  615.         isindex = FALSE;
  616.     }
  617.     else
  618.     {
  619.         isindex = TRUE;
  620.  
  621.         /* there is a tuple in the indexes relation */
  622.         opencatalog("relation", OR_WRITE);
  623.         clearkeys(&Reldes);
  624.         setkey(&Reldes, &rkey, ind.irelidp, RELID);
  625.         setkey(&Reldes, &rkey, ind.iownerp, RELOWNER);
  626.  
  627.         /* see if the primary relation exists */
  628.         if (i = getequal(&Reldes, &rkey, &rel, &rtid))
  629.         {
  630.             /* no it doesn't */
  631.             if (i < 0)
  632.                 syserr("ISNDX: getequal=%d", i);
  633.  
  634.             /* what should be done about it */
  635.             printf("\tNo primary relation for index:\n\t");
  636.             printup(&Inddes, &ind);
  637.             if (ask("\tDelete?"))
  638.             {
  639.                 /*
  640.                 ** get rid of indexes tuple,
  641.                 ** a FALSE return will also get rid
  642.                 ** of the relation tuple
  643.                 */
  644.                 if (i = delete(&Inddes, &itid))
  645.                     syserr("ISNDX: delete=%d", i);
  646.                 isindex = FALSE;
  647.             }
  648.         }
  649.         else if (!(rel.relindxd > 0) || (rel.relstat & S_INDEX) == S_INDEX)
  650.         {
  651.             /*
  652.             ** the primary tuple exists but isn't marked correctly
  653.             */
  654.             printf("\t%.12s is index for:\n\t", rel.relid);
  655.             printup(&Reldes, &rel);
  656.             if (ask("\tMark as indexed? "))
  657.             {
  658.                 rel.relstat |= S_INDEX;
  659.                 rel.relindxd = SECBASE;
  660.                 if (i = replace(&Reldes, &rtid, &rel, FALSE))
  661.                     syserr("ISNDX: replace=%d", i);
  662.             }
  663.         }
  664.     }
  665.     return (isindex);
  666. }
  667. /*
  668. ** HAVETREE -- check tree catalog for an entry with right name and owner
  669. **
  670. **    The 'id' and 'own' parameters are used to look in the tree catalog
  671. **    for at least on tuple that also has a 'treetype' of 'mdvalue'.
  672. **
  673. **    If any tuples are found, havetree returns TRUE, else FALSE
  674. */
  675.  
  676. havetree(id, own, mdvalue)
  677. char    id[MAXNAME];
  678. char    own[2];
  679. int    mdvalue;
  680. {
  681.     extern DESC    Treedes;
  682.     register int    i;
  683.     struct tree    tkey, trent;
  684.     TID        ttid, thitid;
  685.  
  686.     /* search tree relation for tuple that matches */
  687.     opencatalog("tree", OR_WRITE);
  688.     clearkeys(&Treedes);
  689.     setkey(&Treedes, &tkey, id, TREERELID);
  690.     setkey(&Treedes, &tkey, own, TREEOWNER);
  691.     setkey(&Treedes, &tkey, &mdvalue, TREETYPE);
  692.  
  693.     /* set search limit tids from the key */
  694.     if (i = find(&Treedes, EXACTKEY, &ttid, &thitid, &tkey))
  695.         syserr("HAVETREE: find=%d", i);
  696.  
  697.     for (;;)
  698.     {
  699.         i = get(&Treedes, &ttid, &thitid, &trent, TRUE);
  700.  
  701.         if (i < 0)
  702.             syserr("HAVETREE: get=%d", i);
  703.         if (i > 0)
  704.             break;    /* finished, didn't find one */
  705.         
  706.         if (kcompare(&Treedes, &tkey, &trent) == 0)
  707.             return (TRUE);
  708.     }
  709.     return (FALSE);
  710. }
  711. /*
  712. ** ISPROT -- check in the 'protect' catalog for a tuple with right name, owner
  713. **
  714. **    search the 'protect' catalog for at least on tuple with matches the
  715. **    values in the parameters. If 'treeid' is >= 0 then it is not used as
  716. **    a key.
  717. **
  718. **    if one is found, returns TRUE, otherwise, returns FALSE
  719. */
  720.  
  721. isprot(id, own, treeid)
  722. char    id[MAXNAME];
  723. char    own[2];
  724. int    treeid;
  725. {
  726.     extern DESC    Prodes;
  727.     register int    i;
  728.     struct protect    pkey, pent;
  729.     TID        ptid, phitid;
  730.  
  731.     /* search the protect relation for at least on matching tuple */
  732.     opencatalog("protect", OR_WRITE);
  733.     clearkeys(&Prodes);
  734.     setkey(&Prodes, &pkey, id, PRORELID);
  735.     setkey(&Prodes, &pkey, own, PRORELOWN);
  736.     if (treeid >= 0)
  737.         setkey(&Prodes, &pkey, &treeid, PROTREE);
  738.  
  739.     /* set search limit tids from the keys */
  740.     if (i = find(&Prodes, EXACTKEY, &ptid, &phitid, &pkey))
  741.         syserr("ISPROT: find=%d", i);
  742.  
  743.     for (;;)
  744.     {
  745.         i = get(&Prodes, &ptid, &phitid, &pent, TRUE);
  746.  
  747.         if (i < 0)
  748.             syserr("ISPROT: get=%d", i);
  749.         if (i > 0)
  750.             break;    /* finished, didn't find one */
  751.         
  752.         if (kcompare(&Prodes, &pkey, &pent) == 0)
  753.             return (TRUE);
  754.     }
  755.     return (FALSE);
  756. }
  757. /*
  758. ** ISINTEG -- check for a tuple in 'integrities'
  759. **
  760. **    searches the integrities relation for 'id' and 'own'.
  761. **
  762. **    returns TRUE if one is found, else FALSE
  763. */
  764.  
  765. isinteg(id, own, treeid)
  766. char    id[MAXNAME];
  767. char    own[2];
  768. int    treeid;
  769. {
  770.     extern DESC        Intdes;
  771.     register int        i;
  772.     struct integrity    inkey, integ;
  773.     TID            intid, inhitid;
  774.  
  775.     /* search the entire relation for a tuple that matches */
  776.     opencatalog("integrities", OR_WRITE);
  777.     clearkeys(&Intdes);
  778.     setkey(&Intdes, &inkey, id, INTRELID);
  779.     setkey(&Intdes, &inkey, own, INTRELOWNER);
  780.     if (treeid >= 0)
  781.         setkey(&Intdes, &inkey, &treeid, INTTREE);
  782.  
  783.     /* set the search limit tids from the key */
  784.     if (i = find(&Intdes, EXACTKEY, &intid, &inhitid, &inkey))
  785.         syserr("ISINTEG: find=%d", i);
  786.     
  787.     for (;;)
  788.     {
  789.         i = get(&Intdes, &intid, &inhitid, &integ, TRUE);
  790.  
  791.         if (i < 0)
  792.             syserr("ISINTEG: get=%d", i);
  793.         if (i > 0)
  794.             break;    /* finished, didn't find one */
  795.         
  796.         if (kcompare(&Intdes, &inkey, &integ) == 0)
  797.             return (TRUE);
  798.     }
  799.     return (FALSE);
  800. }
  801. /*
  802. ** CHECKTREE -- check the tree catalog against the others
  803. */
  804.  
  805. checktree()
  806.     extern DESC    Treedes, Reldes;
  807.     register int    i;
  808.     struct tree    tkey, trent;
  809.     TID        ttid, thitid;
  810.     struct relation    rkey, rel;
  811.     TID        rtid;
  812.  
  813.     /* search the entire tree catalog */
  814.     opencatalog("tree", OR_WRITE);
  815.     clearkeys(&Treedes);
  816.     if (i = find(&Treedes, NOKEY, &ttid, &thitid))
  817.         syserr("CHECKTREE: find=%d", i);
  818.     
  819.     /* for each tuple in 'tree' */
  820.     for (;;)
  821.     {
  822.         i = get(&Treedes, &ttid, &thitid, &trent, TRUE);
  823.         if (i > 0)
  824.             break;    /* finished */
  825.         if (i < 0)
  826.             syserr("CHECKTREE: get=%d", i);
  827.         
  828.         /* verify that a tuple exists in the relation relation */
  829.         opencatalog("relation", OR_WRITE);
  830.         clearkeys(&Reldes);
  831.         setkey(&Reldes, &rkey, trent.treerelid, RELID);
  832.         setkey(&Reldes, &rkey, trent.treeowner, RELOWNER);
  833.  
  834.         /* fetch the tuple */
  835.         if (i = getequal(&Reldes, &rkey, &rel, &rtid))
  836.         {
  837.             /*
  838.             ** Oops, a tuple doesn't exist in the relation
  839.             ** relation.
  840.             **
  841.             ** maybe it's just a fatal error
  842.             */
  843.             if (i < 0)
  844.                 syserr("CHECKTREE: getequal=%d", i);
  845.  
  846.             /* not a fatal error, what to do about it? */
  847.             printf("\tNo relation tuple for:\n\t");
  848.             printup(&Treedes, &trent);
  849.             if (ask("\tDelete? "))
  850.             {
  851.                 if (i = delete(&Treedes, &ttid))
  852.                     syserr("CHECKTREE: delete=%d", i);
  853.                 continue;    /* go on to next tuple */
  854.             }
  855.         }
  856.         else
  857.         {
  858.             /*
  859.             ** Ah. A tuple does exist.
  860.             **
  861.             ** If the relstat bits are correct then we can stop
  862.             ** here since elsewhere the 'protect' and 'integrity'
  863.             ** entries were verified.
  864.             */
  865.             switch (trent.treetype)
  866.             {
  867.               case mdVIEW:
  868.                 /* mere existence is sufficient */
  869.                 break;
  870.  
  871.               case mdPROT:
  872.                 if ((rel.relstat & S_PROTUPS) != S_PROTUPS)
  873.                 {
  874.                     printf("\tNo 'protect' entry for:\n\t");
  875.                 deltup:
  876.                     printup(&Treedes, &trent);
  877.                     if (ask("\tDelete? "))
  878.                     {
  879.                         if (i = delete(&Treedes, &ttid))
  880.                             syserr("CHECKTREE: delete=%d", i);
  881.                         continue;
  882.                     }
  883.                 }
  884.                 break;
  885.  
  886.               case mdINTEG:
  887.                 if ((rel.relstat & S_INTEG) != S_INTEG)
  888.                 {
  889.                     printf("\tNo 'integrities' entry for:\n\t");
  890.                     goto    deltup;
  891.                 }
  892.                 break;
  893.  
  894.               default:
  895.                 syserr("Unknown treetype: %d\n", trent.treetype);
  896.             }
  897.         }
  898.     }
  899. }
  900. /*
  901. **  CHECKPROTECT
  902. */
  903.  
  904. checkprotect()
  905. {
  906.     register int    i;
  907.     extern DESC    Reldes, Prodes;
  908.     struct protect    pkey, pent;
  909.     TID        ptid, phitid;
  910.     struct relation    rkey, rel;
  911.     TID        rtid;
  912.  
  913.     /* for each entry in the 'protect' relation */
  914.     opencatalog("protect", OR_WRITE);
  915.     clearkeys(&Prodes);
  916.     if (i = find(&Prodes, NOKEY, &ptid, &phitid))
  917.         syserr("CHECKPROTECT: find=%d", i);
  918.     
  919.     for (;;)
  920.     {
  921.         i = get(&Prodes, &ptid, &phitid, &pent, TRUE);
  922.         if (i > 0)
  923.             break;    /* finished */
  924.         if (i < 0)
  925.             syserr("CHECKPROTECT: get=%d", i);
  926.  
  927.         /* verify that a tuple exists in 'relation' */
  928.         opencatalog("relation", OR_WRITE);
  929.         clearkeys(&Reldes);
  930.         setkey(&Reldes, &rkey, pent.prorelid, RELID);
  931.         setkey(&Reldes, &rkey, pent.prorelown, RELOWNER);
  932.  
  933.         /* fetch the tuple if possible */
  934.         if (i = getequal(&Reldes, &rkey, &rel, &rtid))
  935.         {
  936.             /*
  937.             ** Oops.  A tuple doesn't exits in 'relation'
  938.             **
  939.             ** Maybe it's just a fatal error.
  940.             */
  941.             if (i < 0)
  942.                 syserr("CHECKPROTECT: getequal=%d", i);
  943.             
  944.             /* not a fatal error, what to do? */
  945.             printf("\tNo relation for 'protect' entry:\n\t");
  946.             printup(&Prodes, &pent);
  947.             if (ask("\tRemove 'protect' entry? "))
  948.             {
  949.                 if (i = delete(&Prodes, &ptid))
  950.                     syserr("CHECKPROTECT: delete=%d", i);
  951.                 continue;    /* go on to next tuple */
  952.             }
  953.         }
  954.         else
  955.         {
  956.             /* 'relation' entry exists, check for the tree entry */
  957.             if (pent.protree >= 0)
  958.             {
  959.                 if (!havetree(pent.prorelid, pent.prorelown, mdPROT))
  960.                 {
  961.                     /* no tuples in 'tree' */
  962.                     printf("\tNo tree for:\n\t");
  963.                     printup(&Prodes, &pent);
  964.                     if (ask("\tDelete entry and fix relation status bits? "))
  965.                     {
  966.                         if (i = delete(&Prodes, &pent))
  967.                             syserr("CHECKPROTECT: delete=%d", i);
  968.                         rel.relstat &= ~S_PROTUPS;
  969.                         if (i = replace(&Reldes, &rtid, &rel, FALSE))
  970.                             syserr("CHECKPROTECT: replace=%d", i);
  971.                         continue;    /* go on to next tuple */
  972.                     }
  973.                 }
  974.             }
  975.             if ((rel.relstat & S_PROTUPS) != S_PROTUPS)
  976.             {
  977.                 /* bits not set correctly */
  978.                 printf("\tIncorrect relation status bits for:\n\t");
  979.                 printup(&Reldes, &rel);
  980.                 if (ask("\tAdjust? "))
  981.                 {
  982.                     rel.relstat |= S_PROTUPS;
  983.                     if (i = replace(&Reldes, &rtid, &rel, FALSE))
  984.                         syserr("CHECKPROTECT: replace=%d", i);
  985.                     continue;    /* go on to next tuple */
  986.                 }
  987.             }
  988.         }
  989.     }
  990. }
  991. /*
  992. **  CHECKINTEG
  993. */
  994.  
  995. checkinteg()
  996. {
  997.     register int        i;
  998.     extern DESC        Reldes, Intdes;
  999.     struct integrity    inkey, inent;
  1000.     TID            intid, inhitid;
  1001.     struct relation        rkey, rel;
  1002.     TID            rtid;
  1003.  
  1004.     /* for each entry in 'integrities' */
  1005.     opencatalog("integrities", OR_WRITE);
  1006.     clearkeys(&Intdes);
  1007.     if (i = find(&Intdes, NOKEY, &intid, &inhitid))
  1008.         syserr("CHECKINTEG: find=%d", i);
  1009.     
  1010.     for (;;)
  1011.     {
  1012.         i = get(&Intdes, &intid, &inhitid, &inent, TRUE);
  1013.         if (i > 0)
  1014.             break;    /* finished */
  1015.         if (i < 0)
  1016.             syserr("CHECKINTEG: get=%d", i);
  1017.  
  1018.         /* verify that a tuple exists in 'relation' */
  1019.         opencatalog("relation", OR_WRITE);
  1020.         clearkeys(&Reldes);
  1021.         setkey(&Reldes, &rkey, inent.intrelid, RELID);
  1022.         setkey(&Reldes, &rkey, inent.intrelowner, RELOWNER);
  1023.  
  1024.         /* fetch the tuple if possible */
  1025.         if (i = getequal(&Reldes, &rkey, &rel, &rtid))
  1026.         {
  1027.             /*
  1028.             ** Oops.  A tuple doesn't exits in 'relation'
  1029.             **
  1030.             ** Maybe it's just a fatal error.
  1031.             */
  1032.             if (i < 0)
  1033.                 syserr("CHECKINTEG: getequal=%d", i);
  1034.             
  1035.             /* not a fatal error, what to do? */
  1036.             printf("\tNo relation for 'integrities' entry:\n\t");
  1037.             printup(&Intdes, &inent);
  1038.             if (ask("\tRemove 'integrities' entry? "))
  1039.             {
  1040.                 if (i = delete(&Intdes, &intid))
  1041.                     syserr("CHECKINTEG: delete=%d", i);
  1042.                 continue;    /* go on to next tuple */
  1043.             }
  1044.         }
  1045.         else
  1046.         {
  1047.             /* 'relation' entry exists, check for the tree entry */
  1048.             if (inent.inttree >= 0)
  1049.             {
  1050.                 if (!havetree(inent.intrelid, inent.intrelowner, mdINTEG))
  1051.                 {
  1052.                     /* no tuples in 'tree' */
  1053.                     printf("\tNo tree for:\n\t");
  1054.                     printup(&Intdes, &inent);
  1055.                     if (ask("\tDelete entry and fix relation status bits? "))
  1056.                     {
  1057.                         if (i = delete(&Intdes, &inent))
  1058.                             syserr("CHECKINTEG: delete=%d", i);
  1059.                         rel.relstat &= ~S_INTEG;
  1060.                         if (i = replace(&Reldes, &rtid, &rel, FALSE))
  1061.                             syserr("CHECKINTEG: replace=%d", i);
  1062.                         continue;    /* go on to next tuple */
  1063.                     }
  1064.                 }
  1065.             }
  1066.             if ((rel.relstat & S_INTEG) != S_INTEG)
  1067.             {
  1068.                 /* bits not set correctly */
  1069.                 printf("\tIncorrect relation status bits for:\n\t");
  1070.                 printup(&Reldes, &rel);
  1071.                 if (ask("\tAdjust? "))
  1072.                 {
  1073.                     rel.relstat |= S_INTEG;
  1074.                     if (i = replace(&Reldes, &rtid, &rel, FALSE))
  1075.                         syserr("CHECKINTEG: replace=%d", i);
  1076.                     continue;    /* go on to next tuple */
  1077.                 }
  1078.             }
  1079.         }
  1080.     }
  1081. }
  1082.